package modules;

import fenetres.FenetreGenerale;
import interfaces.*;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;


/**
 * Classe liée au traitement des plugins
 * Recherche, Comparaison, Manipulation ...... 
 * C'est une classe modèle ou de type métier qui fournit à l'application des différents services
 * liés à la gestion des composantes
 * @author Amine HALLILI amine.hallili@gmail.com
 *
 */
public class Traitement {
	
	
	
	
	/**
	 * Permet le chargement d'un plugin implementant l'interface TreeInterface
	 * Cette interface definit un explorateur de fichier
	 * @param l une list de classes
	 * @return TreeInerface or null si aucune classe n'implemente l'interface TreeInterface 
	 */
	public static TreeInterface chargerExplorateur(List<Class<?>> l)
	{
		TreeInterface ti=null;
		for(Class<?> cl : l)
		{
			Class<?>[] interfaces = cl.getInterfaces();
			for(Class<?> i : interfaces)
			{
				if(i.getName() == "interfaces.TreeInterface")
				{
					try {
						ti = (TreeInterface)cl.newInstance();
						if(ti.isDefault())
							return ti;
					}
					catch (InstantiationException e) {e.printStackTrace();}
					catch (IllegalAccessException e) {e.printStackTrace();}
				}
			}
		}
		
		
		return ti;
	}
	
	
	/**
	 * Permet le chargement d'un plugin implementant l'interface RepertoireInterface
	 * Cette interface definit un repertoire de fichiers
	 * @param l une list de classes
	 * @return RepertoireInerface or null si aucune classe n'implemente l'interface RepertoireInterface 
	 */
	public static RepertoireInterface chargerRepertoire(List<Class<?>> l)
	{
		RepertoireInterface ri=null;
		for(Class<?> cl : l)
		{
			Class<?>[] interfaces = cl.getInterfaces();
			for(Class<?> i : interfaces)
			{
				if(i.getName() == "interfaces.RepertoireInterface")
				{
					try {
						ri = (RepertoireInterface)cl.newInstance();
						if(ri.isDefault())
							return ri;
					}
					catch (InstantiationException e) {e.printStackTrace();}
					catch (IllegalAccessException e) {e.printStackTrace();}
				}
			}
		}
		
		
		return ri;
	}
	
	
	
	/**
	 * Permet le chargement d'une liste de plugins implementant l'interface RepertoireInterface
	 * Cette interface definit un explorateur de fichier
	 * @param l une list de classes
	 * @return RepertoireInerface or null si aucune classe n'implemente l'interface RepertoireInterface 
	 */
	public static List<RepertoireInterface> chargerRepertoirePlugins(List<Class<?>> l)
	{
		List<RepertoireInterface> pi=new ArrayList<RepertoireInterface>();
		for(Class<?> cl : l)
		{
			Class<?>[] interfaces = cl.getInterfaces();
			for(Class<?> i : interfaces)
			{
				if(i.getName() == "interfaces.RepertoireInterface")
				{
					try {
						pi.add( (RepertoireInterface)cl.newInstance());
					}
					catch (InstantiationException e) {e.printStackTrace();}
					catch (IllegalAccessException e) {e.printStackTrace();}
				}
			}
		}	
		return pi;
	}
	
	
	
	
	/**
	 * Permet le chargement d'un plugin implementant l'interface PluginInterface
	 * Cette interface definit un explorateur de fichier
	 * @param l une list de classes
	 * @return PluginInerface or null si aucune classe n'implemente l'interface PluginInterface 
	 */
	public static List<PluginInterface> chargerPlugins(List<Class<?>> l)
	{
		List<PluginInterface> pi=new ArrayList<PluginInterface>();
		for(Class<?> cl : l)
		{
			Class<?>[] interfaces = cl.getInterfaces();
			for(Class<?> i : interfaces)
			{
				if(i.getName() == "interfaces.PluginInterface")
				{
					try {
						pi.add( (PluginInterface)cl.newInstance());
					}
					catch (InstantiationException e) {e.printStackTrace();}
					catch (IllegalAccessException e) {e.printStackTrace();}
				}
			}
		}	
		return pi;
	}
	
	
	
	
	/**
	 * extrait tous les plugins de la liste des classes
	 * @param l List<Class<?>> une liste de classes
	 * @return iPlugin or null si aucune classe n'implemente l'interface TreeInterface 
	 */
	public static List<IPlugin> chargerAllPlugins(List<Class<?>> l)
	{
		List<IPlugin> pi=new ArrayList<IPlugin>();
		for(Class<?> cl : l)
		{
			Class<?>[] interfaces = cl.getInterfaces();
			for(Class<?> i : interfaces)
			{
				if(i.getName() == "interfaces.PluginInterface" || i.getName() == "interfaces.TreeInterface" || i.getName() == "interfaces.RepertoireInterface")
				{
					try {
						pi.add( (IPlugin)cl.newInstance());
					}
					catch (InstantiationException e) {e.printStackTrace();}
					catch (IllegalAccessException e) {e.printStackTrace();}
				}
			}
		}	
		return pi;
	}
	
	
	/**
	 * met un Plugin comme plugin par défaut et change l'etat de tous les autres plugin de meme type
	 * @param <T>
	 * @param c IPlugin le plugin à mettre par défaut
	 * @param iPlugins List<IPlugin> liste de tous les plugins
	 */
	public static <T> List<T> setDefaut(IPlugin c, List<T> iPlugins)
	{
		c.setDefault(true);
		for(T iPlugin : iPlugins)
		{
			if(compareExtension(c.getExtension(), ((IPlugin)iPlugin).getExtension()))
				if(!c.getClass().getName().equals(iPlugin.getClass().getName()))
					((IPlugin)iPlugin).setDefault(false);
		}
		return iPlugins;
	}
	
	
	public static boolean compareExtension(String[] a,String[] b)
	{
		if(a.length != b.length)
			return false;
		else
			for(int i=0 ; i<a.length ; i++)
				if(a[i] != b[i])
					return false;
		
		return true;
	}
	
	
	
	/**
	 * Cette fonction renvoi le plugin prenant en compte un fichier dont en passe son extension en parametre
	 * @param extension String
	 * @param l 		List<PluginInterface>
	 * @return PluginInterface or null
	 */
	public static PluginInterface getRightPlugin(String extension , List<PluginInterface> l)
	{
		PluginInterface pRes = null;
		for(PluginInterface p : l)
		{
			String[] ext = p.getExtension();
			for(String e : ext)
			if(extension.equals(e))
			{
				if(p.isDefault())
					return p;
				else
					pRes=p;
			}
		}
		return pRes;
	}
	
	
	/**
	 * Calcule l'extension d'un fichier et la renvoie
	 * @param f File
	 * @return extension String
	 */
	public static String getFileExtension(File f)
	{
		int index = f.getName().lastIndexOf(".");
		
		return f.getName().substring(index+1, f.getName().length());
	}
	
	
	/**
	 * Sauvegarde l'etat de l'application
	 * @param f
	 */
	public static void sauvegarderFenetre(FenetreGenerale f)
	{
		Properties prop = new Properties();
		try 
		{
			FileOutputStream fos = new FileOutputStream("Explorateur.properties");
			
			
			if(f.getRi().getlastOpenedDir() != null)
				prop.setProperty("lastOpenedDir", f.getRi().getlastOpenedDir().getAbsolutePath());
			else
				prop.setProperty("lastOpenedDir", "null");
			prop.setProperty("x", String.valueOf(f.getBounds().x));
			prop.setProperty("y", String.valueOf(f.getBounds().y));
			prop.setProperty("width", String.valueOf(f.getBounds().width));
			prop.setProperty("height", String.valueOf(f.getBounds().height));
			
			for(IPlugin iplugin : f.getiPlugins())
			{
				prop.setProperty(iplugin.getClass().getName(), String.valueOf(iplugin.isDefault()));
			}
			
			
			prop.store(fos, "Author: Amine HALLILI amine.hallili@gmail.com");
			fos.close();
		} 
		catch(IOException e) { e.printStackTrace();	}
	}
	
	
	
	/**
	 * charger les proprietés des objets dans le fichier de configuration
	 * @param f
	 */
	public static void chargerFenetre(FenetreGenerale f)
	{
		if(new File("Explorateur.properties").exists())
		{
			Properties prop = new Properties();
			try 
			{
				FileInputStream fis = new FileInputStream("Explorateur.properties");
				prop.load(fis);
				
				
				f.setBounds(Integer.parseInt(prop.getProperty("x")), Integer.parseInt(prop.getProperty("y")), Integer.parseInt(prop.getProperty("width")), Integer.parseInt(prop.getProperty("height")));
				
				for(IPlugin iplugin : f.getiPlugins())
				{
					if(prop.get(iplugin.getClass().getName()) != null)
					{
						if(((String)prop.get(iplugin.getClass().getName())).equals("true"))
							iplugin.setDefault(true);
						else
							iplugin.setDefault(false);
					}
				}
				for(PluginInterface iplugin : f.getPi())
				{
					if(prop.get(iplugin.getClass().getName()) != null)
					{
						if(((String)prop.get(iplugin.getClass().getName())).equals("true"))
							iplugin.setDefault(true);
						else
							iplugin.setDefault(false);
					}
				}
				if(f.getRi() != null)
					f.getScrollCentre().getViewport().add((f.getRi().getFrame(new File(prop.getProperty("lastOpenedDir")), f.getPi())));
				
				
				fis.close();
			} 
			catch(IOException e) { e.printStackTrace();	}
		}
	}
	
	/**
	 * permet le changement d'état des plugins de lansement de fichier en des plugins générals.
	 * @param lp liste des plugins
	 * @return
	 */
	public static List<IPlugin> convertPluginInterfaceToIPlugin(List<PluginInterface> lp)
	{
		List<IPlugin> l = new ArrayList<IPlugin>();
		for(PluginInterface c :lp)
			l.add((IPlugin)c);
		return l;
	}
	
}
